//! Statement parser for NRC language
//!
//! This module is organized into sub-modules by statement type:
//! - variable_stmt: Variable and constant declarations
//! - control_flow: If, return, break, continue statements
//! - loops: For and while loops
//! - match_stmt: Match statement and pattern matching
//! - error_handling: (removed - now using panic/recover)
//! - concurrency: Select and go statements
//! - blocks: Block statements
//! - other_stmts: Export and defer statements
//! - tests: Unit tests

use super::{parse_expression, Parser};
use crate::ast::expr::Expression;
use crate::ast::stmt::{
    AssignmentOp, AssignmentStmt, AssignmentTarget, ConstantDeclStmt, FieldAccessTarget,
    IndexAccessTarget, Statement, VariableDeclStmt,
};
use crate::error::{CompilerError, Result};
use crate::lexer::token::Token;

// Sub-modules
pub mod blocks;
pub mod concurrency;
pub mod control_flow;
pub mod loops;
pub mod match_stmt;
pub mod other_stmts;
pub mod recover;
pub mod variable_stmt;

#[cfg(test)]
mod tests;

// Re-exports
pub use blocks::parse_block_statement;
pub use concurrency::{parse_go_statement, parse_select_statement};
pub use control_flow::{
    parse_break_statement, parse_continue_statement, parse_if_statement, parse_if_var_statement,
    parse_return_statement,
};
pub use loops::{parse_for_statement, parse_while_statement};
pub use match_stmt::parse_match_statement;
pub use other_stmts::{parse_defer_statement, parse_export_statement};
pub use recover::parse_recover_statement;
pub use variable_stmt::{parse_constant_declaration, parse_variable_declaration};

/// Parse a statement
pub fn parse_statement(parser: &mut Parser) -> Result<Option<Statement>> {
    if parser.is_at_end() {
        return Ok(None);
    }

    // Skip any leading semicolons (from auto-insertion)
    while parser.check(&Token::Semicolon) {
        parser.advance()?;
        if parser.is_at_end() {
            return Ok(None);
        }
    }

    match parser.peek() {
        Some(token) => match &token.token {
            Token::Var => {
                let decl = parse_variable_declaration(parser)?;
                Ok(Some(Statement::VariableDecl(VariableDeclStmt {
                    name: decl.name,
                    var_type: decl.var_type,
                    initializer: decl.initializer,
                    mutable: decl.mutable,
                    location: decl.location,
                })))
            }
            Token::Const => {
                let decl = parse_constant_declaration(parser)?;
                Ok(Some(Statement::ConstantDecl(ConstantDeclStmt {
                    name: decl.name,
                    const_type: decl.const_type,
                    value: decl.value,
                    location: decl.location,
                })))
            }
            Token::If => {
                let is_if_var = matches!(
                    parser.peek_ahead(1).map(|t| &t.token),
                    Some(Token::Var)
                );
                if is_if_var {
                    let stmt = parse_if_var_statement(parser)?;
                    Ok(Some(stmt))
                } else {
                    let stmt = parse_if_statement(parser)?;
                    Ok(Some(Statement::If(stmt)))
                }
            }
            Token::For => {
                let stmt = parse_for_statement(parser)?;
                Ok(Some(Statement::For(stmt)))
            }
            Token::While => {
                let stmt = parse_while_statement(parser)?;
                Ok(Some(Statement::While(stmt)))
            }
            Token::Match => {
                let stmt = parse_match_statement(parser)?;
                Ok(Some(Statement::Match(stmt)))
            }
            Token::Return => {
                let stmt = parse_return_statement(parser)?;
                Ok(Some(Statement::Return(stmt)))
            }
            Token::Break => {
                let stmt = parse_break_statement(parser)?;
                Ok(Some(Statement::Break(stmt)))
            }
            Token::Continue => {
                let stmt = parse_continue_statement(parser)?;
                Ok(Some(Statement::Continue(stmt)))
            }
            Token::Defer => {
                let stmt = parse_defer_statement(parser)?;
                Ok(Some(Statement::Defer(stmt)))
            }
            Token::Recover => {
                let stmt = parse_recover_statement(parser)?;
                Ok(Some(Statement::Recover(stmt)))
            }
            Token::Select => {
                let stmt = parse_select_statement(parser)?;
                Ok(Some(Statement::Select(Box::new(stmt))))
            }
            Token::Go => {
                let stmt = parse_go_statement(parser)?;
                Ok(Some(Statement::Go(stmt)))
            }
            Token::Export => {
                let stmt = parse_export_statement(parser)?;
                Ok(Some(Statement::Export(stmt)))
            }
            Token::LeftBrace => {
                let stmt = parse_block_statement(parser)?;
                Ok(Some(Statement::Block(stmt)))
            }
            _ => {
                // Try to parse as an expression or assignment statement
                if let Some(expr) = parse_expression(parser)? {
                    // Check if this is an assignment (identifier = value or field.access = value)
                    if parser.check(&Token::Assign) {
                        parser.advance()?; // consume '='

                        // Parse the value expression
                        let value = parse_expression(parser)?.ok_or_else(|| {
                            CompilerError::syntax(
                                parser.current_location().line,
                                parser.current_location().column,
                                "Expected expression after '='",
                            )
                        })?;

                        // Convert the LHS expression to an assignment target
                        let target = match expr {
                            Expression::Variable(name) => AssignmentTarget::Variable(name),
                            Expression::FieldAccess(field_access) => {
                                AssignmentTarget::FieldAccess(FieldAccessTarget {
                                    object: *field_access.object,
                                    field: field_access.field,
                                    location: field_access.location,
                                })
                            }
                            Expression::IndexAccess(index_access) => {
                                AssignmentTarget::IndexAccess(IndexAccessTarget {
                                    object: *index_access.object,
                                    index: *index_access.index,
                                    location: index_access.location,
                                })
                            }
                            Expression::Unary(unary_expr) => {
                                // Check if this is a dereference operation
                                if matches!(unary_expr.operator, crate::ast::expr::UnaryOp::Deref) {
                                    AssignmentTarget::Deref(unary_expr.operand)
                                } else {
                                    return Err(CompilerError::syntax(
                                        parser.current_location().line,
                                        parser.current_location().column,
                                        "Invalid assignment target (only dereference *ptr is supported for unary expressions)"
                                    ));
                                }
                            }
                            _ => {
                                return Err(CompilerError::syntax(
                                    parser.current_location().line,
                                    parser.current_location().column,
                                    "Invalid assignment target (only variables, field access, index access, and dereferences are supported)"
                                ));
                            }
                        };

                        // 可选的分号
                        parser.consume(&Token::Semicolon)?;

                        Ok(Some(Statement::Assignment(AssignmentStmt {
                            target,
                            operator: AssignmentOp::Assign,
                            value,
                            location: parser.current_location(),
                        })))
                    } else {
                        // 可选的分号，支持无分号语法
                        // 在函数体中，单个表达式语句可能没有分号
                        if parser.check(&Token::Semicolon) {
                            parser.advance()?;
                        }
                        Ok(Some(Statement::Expression(expr)))
                    }
                } else {
                    Ok(None)
                }
            }
        },
        None => Ok(None),
    }
}
